package com.example.mq.mqserver.core;

import java.io.Serializable;
import java.util.UUID;

/**
 * 表示一条要传递的消息
 * 1、属性部分：BasicProperties类表示 2、正文部分：byte[]表示
 *
 * Message要在网络中传输，也要写入文件中
 * 则针对Message进行 序列化和反序列化
 * 使用标准库自带的序列化和反序列化，而不使用JSON方式：因为JSON本质是文本格式，里面放的是文本类型的数据。而Message里面存储的是二进制数据
 * 使用标准库自带的：实现一个特定的接口Serializable。只需要实现接口，不需要重写里面的方法
 */
public class Message implements Serializable {
    // 消息属性
    private BasicProperties basicProperties = new BasicProperties(); // 避免调用出现：空指针对象

    // 消息正文
    private byte[] body;

    // 偏移量[offsetBeg,offsetEnd)
    // 偏移量:不需要序列化保存到文件中，所在位置固定了，不需要单独存储（加上transient）
    // 偏移量目的：让内存上的Message对象，快速找到对应硬盘上Message的位置
    // 被transient关键字所修饰的属性，则不会被标准库的序列化方式所序列化
    private transient long offsetBeg = 0; // 消息数据的开头距离文件开头位置的偏移（字节）
    private transient long offsetEnd = 0; // 消息数据的结尾距离文件开头位置的偏移（字节）

    // 表示消息在文件中是否是有效消息（逻辑删除）
    // 0x1：表示有效；0x0：表示无效
    private byte isValid = 0x1;

    // 工厂方法：封装创建Message对象的过程
    public static Message createMessageWithId(String routingKey, BasicProperties basicProperties, byte[] body) {
        Message message = new Message();
        if(basicProperties != null) {
            message.setBasicProperties(basicProperties);
        }
        message.setMessageId("M_" + UUID.randomUUID()); // 以"M_"作为前缀，表示是消息id
        message.setRoutingKey(routingKey);
        message.body = body;

        // 此处只是在内存中创建一个Message对象,basicProperties和body是Message的核心内容
        // offsetBeg、offsetEnd、isValid，在消息持久化才会用到，在把消息写进文件之前进行设定
        return message;
    }

    public String getMessageId() {
        return basicProperties.getMessageId();
    }

    public void setMessageId(String messageId) {
        basicProperties.setMessageId(messageId);
    }

    public String getRoutingKey() {
        return basicProperties.getRoutingKey();
    }

    public void setRoutingKey(String routingKey) {
        basicProperties.setRoutingKey(routingKey);
    }

    public int getDeliverModel() {
        return basicProperties.getDeliverModel();
    }

    public void setDeliverModel(int deliverModel) {
        basicProperties.setDeliverModel(deliverModel);
    }

    public BasicProperties getBasicProperties() {
        return basicProperties;
    }

    public void setBasicProperties(BasicProperties basicProperties) {
        this.basicProperties = basicProperties;
    }

    public byte[] getBody() {
        return body;
    }

    public void setBody(byte[] body) {
        this.body = body;
    }

    public long getOffsetBeg() {
        return offsetBeg;
    }

    public void setOffsetBeg(long offsetBeg) {
        this.offsetBeg = offsetBeg;
    }

    public long getOffsetEnd() {
        return offsetEnd;
    }

    public void setOffsetEnd(long offsetEnd) {
        this.offsetEnd = offsetEnd;
    }

    public byte getIsValid() {
        return isValid;
    }

    public void setIsValid(byte isValid) {
        this.isValid = isValid;
    }
}